#pragma once

#include <base.h>
#include <compl/atmops.h>
/* llsc的汇编实现 */
typedef dword_t		llword_t;
typedef struct
{
	union{
		llword_t val;
		struct{
			word_t cnt;
			word_t rval;
		};
	};
	llword_t *ptr;
}  llsc_t;

// #ifdef __COMPCERT_C__
// 	static inline dword_t __sync_val_compare_and_swap(dword_t * ptr, dword_t old_val, dword_t new_val)
// 	{
// 		bool_t result;
// 		asm volatile
// 		(
// 		"lock cmpxchg16b %1\n\t"
// 		"setz %0"	   // on gcc6 and later, use a flag output constraint instead
// 		: "=q" ( result )
// 		, "+m" ( *ptr )
// 		, "+d" ( old_val.hword )
// 		, "+a" ( old_val.lword )
// 		: "c" ( new_val.hword )
// 		, "b" ( new_val.lword )
// 		: "cc", "memory"
// 		);
// 		return result;
// 	}
// #endif

static inline word_t ld_link(llsc_t *x, llword_t *ptr){
	// word_t val;
	
	x->ptr = ptr;
	

	/* FIXME: 这里只是读取，是否不需要用lock前缀? 不用lock前缀会出错 */

	/* amd64这个性能会不会差得多? */
	char res;
	x->val.lword = 0;
	x->val.hword = 0;
	asm volatile("lock cmpxchg16b\t%1"
		: "=@cce" (res), "+m" (*ptr), "+a" (x->val.lword), "+d" (x->val.hword)
		: "b"(x->val.lword), "c" (x->val.lword)
		: "memory", "cc");
	
	//x->val = __sync_val_compare_and_swap(x->ptr, 0, 0);
	// x->val = *(dword_t volatile *)x->ptr;
	/* 分两次读有问题吗？ 先读头部再读版本好像没问题 */
	// x->val.hword = atm_ld(&((dword_t*)x->ptr)->hword);
	// x->val.lword = atm_ld(&((dword_t*)x->ptr)->lword);
	return x->rval;
}

static inline bool_t st_cond(llsc_t *x, word_t new_val)
{
	llword_t new_cntval = new_dword(new_val, x->cnt + 1);
	
	char res;
	asm volatile("lock cmpxchg16b\t%1"
		: "=@cce" (res), "+m" (*(x->ptr)), "+a" (x->val.lword), "+d" (x->val.hword)
		: "b"(new_cntval.lword), "c" (new_cntval.hword)
		: "memory", "cc");
	return res;
	// llword_t old_val = x->val;
	// *((__uint128_t *)&x->val) = __sync_val_compare_and_swap((__uint128_t *)x->ptr, *((__uint128_t *)&old_val), *((__uint128_t *)&new_cntval));
	// return (*((__uint128_t *)&old_val) == *((__uint128_t *)&x->val));
}

#define ld_link_acq(x, ptr)		ld_link(x, ptr)
#define st_cond_rel(x, new_val)		st_cond(x, new_val)

